package com.huanxing.cloud.mall.api.notify;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result;
import com.huanxing.cloud.common.core.constant.SecurityConstants;
import com.huanxing.cloud.common.core.entity.Result;
import com.huanxing.cloud.mall.api.service.IOrderInfoService;
import com.huanxing.cloud.mall.api.service.IOrderLogisticsService;
import com.huanxing.cloud.mall.common.entity.OrderInfo;
import com.huanxing.cloud.mall.common.feign.FeignWxPayService;
import com.kuaidi100.sdk.response.SubscribePushParamResp;
import com.kuaidi100.sdk.response.SubscribeResp;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

/**
 * 订单回调
 *
 * @author lijx
 * @since 2022/3/7 14:01
 */
@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("/order/notify")
public class OrderNotify {
  private final IOrderInfoService orderInfoService;
  private final FeignWxPayService feignWxPayService;
  private final IOrderLogisticsService orderLogisticsService;

  @ApiOperation(value = "微信支付回调")
  @PostMapping("/pay/wx")
  public String notifyOrderWx(@RequestBody String notifyData) {
    log.info("微信支付回调:{}" + notifyData);
    // 解密微信支付回调
    Result<WxPayOrderNotifyV3Result> wxPayOrderNotifyV3ResultResult =
        feignWxPayService.notifyOrderData(notifyData, SecurityConstants.SOURCE_IN);
    if (wxPayOrderNotifyV3ResultResult.isOk()) {
      WxPayOrderNotifyV3Result wxPayOrderNotifyV3Result = wxPayOrderNotifyV3ResultResult.getData();
      WxPayOrderNotifyV3Result.DecryptNotifyResult decryptNotifyResult =
          wxPayOrderNotifyV3Result.getResult();
      OrderInfo orderInfo =
          orderInfoService.getOne(
              Wrappers.<OrderInfo>lambdaQuery()
                  .eq(OrderInfo::getOrderNo, decryptNotifyResult.getOutTradeNo()));
      if (ObjectUtil.isNull(orderInfo)) {
        return WxPayNotifyResponse.fail("订单不存在");
      }
      orderInfo.setTradeType(decryptNotifyResult.getTradeType());
      orderInfo.setTransactionId(decryptNotifyResult.getTransactionId());
      try {
        orderInfo.setPaymentTime(LocalDateTimeUtil.parse(decryptNotifyResult.getSuccessTime()));
      } catch (Exception e) {
        log.error("转换错误", e.getMessage());
      }
      orderInfoService.notifyOrder(orderInfo);
    } else {
      return WxPayNotifyResponse.fail("解密失败");
    }
    return WxPayNotifyResponse.success("成功");
  }

  @ApiOperation(value = "支付宝支付回调")
  @PostMapping("/pay/ali")
  public String notifyOrderAli(@RequestBody String notifyData) {
    return "success";
  }

  @ApiOperation(value = "微信退款回调")
  @PostMapping("/refund/wx")
  public String notifyRefundOrderWx(@RequestBody String notifyData) {
    return WxPayNotifyResponse.success("成功");
  }

  /**
   * 订阅推送处理(参照) 订阅成功后，如果该快递单号有轨迹（包括已经签收的单），快递100将会在15分钟-4个小时推送；后面将会4个小时跟踪一次，跟踪到有轨迹变化则推送；
   * 如果订阅成功后，3天查无结果（录错单/快递公司错了/揽收比较晚），快递100将会推送3天查无结果，可以继续重新订阅。
   *
   * <p>回调接口支持自定义参数,比如订阅时回调地址填写的是 http://www.xxx.com?orderId=1233333 可以通过下面这种方式获取到orderId： String
   * orderId = request.getParameter("orderId");
   *
   * <p>返回值必须是下面这样的格式，否则快递100将认为该推送失败，快递100将会重试3次该推送，时间间隔35分钟； 成功结果返回例子：
   * {"result":true,"returnCode":"200","message":"提交成功"}
   *
   * @param request
   * @return: com.kuaidi100.sdk.response.SubscribeResp
   * @author: lijx
   * @time: 2022/6/11
   */
  @ApiOperation(value = "物流信息回调")
  @PostMapping("/logistics")
  public SubscribeResp logisticsOrder(HttpServletRequest request) {
    String logisticsId = request.getParameter("logisticsId");
    SubscribePushParamResp subscribePushParamResp =
        JSONUtil.toBean(request.getParameter("param"), SubscribePushParamResp.class);
    log.info("物流回调:{}", subscribePushParamResp);
    SubscribeResp subscribeResp = new SubscribeResp();
    try {
      orderLogisticsService.notifyLogistics(logisticsId, subscribePushParamResp);
      subscribeResp.setResult(Boolean.TRUE);
      subscribeResp.setReturnCode("200");
      subscribeResp.setMessage("成功");
    } catch (Exception e) {
      subscribeResp.setResult(Boolean.FALSE);
      subscribeResp.setReturnCode("500");
      subscribeResp.setMessage(e.getMessage());
    }

    return subscribeResp;
  }
}
